Skip to content

feat: add prime total rewards card#5626

Merged
cuzz-venus merged 6 commits into
mainfrom
feat/prime-total-rewards
Jun 23, 2026
Merged

feat: add prime total rewards card#5626
cuzz-venus merged 6 commits into
mainfrom
feat/prime-total-rewards

Conversation

@cuzz-venus

@cuzz-venus cuzz-venus commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Jira ticket(s)

VPD-1333

Changes

  • support total reward card
image image image

@changeset-bot

changeset-bot Bot commented Jun 11, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 6085a57

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel

vercel Bot commented Jun 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
dapp-preview Ready Ready Preview Jun 22, 2026 6:06pm
dapp-testnet Ready Ready Preview Jun 22, 2026 6:06pm
venus.io Ready Ready Preview Jun 22, 2026 6:06pm

Request Review

@greptile-apps

greptile-apps Bot commented Jun 11, 2026

Copy link
Copy Markdown

Greptile Summary

This PR implements the Prime Total Rewards and User Rewards cards for the Prime Leaderboard page, adding per-market reward rows with progress bars, a MarketActionsButton that opens an inline market operation modal, and eligibility messaging for non-Prime or zero-reward users. It also extracts the repeated market modal JSX into a reusable MarketFormModal container and gates the UserRewardsSection behind wallet connection.

  • New reward cards (TotalRewardsCard, UserRewardsCard) are wired through thin section wrappers backed by placeholder hooks with explicit TODO comments; the MarketRewardRow zero-total guard from a prior review is now in place.
  • MarketFormModal extraction removes duplicated modal JSX from MarketTable and reuses it in the new MarketActionsButton, which now correctly has an onClick handler.
  • Data and type layering issues remain: the placeholder hooks import their output types from UI component files (inverted dependency), and UserRewardsCard calls useGetPools directly rather than receiving enriched data from its UserRewardsSection wrapper.

Confidence Score: 5/5

Safe to merge; all findings are style and architecture suggestions with no functional defects in the changed code paths.

All reward card logic is straightforward — placeholder data with explicit TODOs, the zero-total guard is present, the modal button is wired up, and wallet-gating for the user section is correctly implemented. The open items (type-import direction, raw hex colour, pool-fetch placement) are clean-up concerns that do not affect correctness or user-visible behaviour at this stage.

UserRewardsCard/index.tsx and the two placeholder hooks (useGetPrimeTotalRewards, useGetPrimeUserRewards) — the type-import coupling and the direct pool-fetch inside the card should be cleaned up before the real API is wired in.

Important Files Changed

Filename Overview
apps/evm/src/pages/PrimeLeaderboard/UserRewardsCard/index.tsx Implements User Rewards card; uses raw hex border-[#805c4e] (design-token violation) and calls useGetPools directly (should be in UserRewardsSection)
apps/evm/src/pages/PrimeLeaderboard/UserRewardsSection/index.tsx Data-container wrapper for the User Rewards card; also contains duplicated raw hex border-[#805c4e]
apps/evm/src/pages/PrimeLeaderboard/TotalRewardsCard/index.tsx Implements the Total Rewards card with per-market progress bars; exports the shared MarketReward type (should be in the hook instead)
apps/evm/src/pages/PrimeLeaderboard/useGetPrimeTotalRewards/index.ts Placeholder hook for total rewards; imports MarketReward type from UI component (inverted dependency direction)
apps/evm/src/pages/PrimeLeaderboard/useGetPrimeUserRewards/index.ts Placeholder hook for user rewards; imports UserMarketReward from UserRewardsCard (same inverted dependency as total rewards hook)
apps/evm/src/pages/PrimeLeaderboard/MarketActionsButton/index.tsx New button component that opens a MarketFormModal; now has a proper onClick handler wiring (previous review concern addressed)
apps/evm/src/containers/MarketFormModal/index.tsx Extracts the market modal into a reusable container; removes duplication from MarketTable
apps/evm/src/pages/PrimeLeaderboard/index.tsx Correctly gates UserRewardsSection behind wallet connection; replaces direct card imports with section wrappers
apps/evm/src/pages/PrimeLeaderboard/TotalRewardsSection/index.tsx Thin data-container wrapper; clean separation between data fetching and presentation
apps/evm/src/pages/PrimeLeaderboard/MarketRewardRow/index.tsx Shared row component with token, formatted reward amount, and progress bar; zero-total guard is in place

Reviews (5): Last reviewed commit: "fix: review comments" | Re-trigger Greptile

<div className="h-1.5 w-18 overflow-hidden rounded-full bg-lightGrey">
<div
className="h-full rounded-full bg-green"
style={{ width: `${Math.min(100, (rewardsCents / totalRewardsCents) * 100)}%` }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 When totalRewardsCents is 0, the expression rewardsCents / totalRewardsCents produces either Infinity (when rewardsCents > 0) or NaN (when both are 0). Math.min(100, Infinity) resolves correctly to 100, but Math.min(100, NaN) returns NaN, making the inline style width: NaN% — an invalid CSS value that the browser silently ignores, leaving the bar collapsed.

Suggested change
style={{ width: `${Math.min(100, (rewardsCents / totalRewardsCents) * 100)}%` }}
style={{
width: `${totalRewardsCents > 0 ? Math.min(100, (rewardsCents / totalRewardsCents) * 100) : 0}%`,
}}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — added a zero-total guard so the bar renders at 0% instead of producing a NaN width.

Comment on lines +21 to +23
const marketRewards = tokens
.slice(0, placeholderMarketRewardsCents.length)
.map((token, index) => ({ token, rewardsCents: placeholderMarketRewardsCents[index] }));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Placeholder tokens are unrelated to Prime markets

useGetTokens() returns all tokens registered in the app's token list, and .slice(0, 2) picks whichever two happen to be first — typically generic tokens like BTC/ETH that have nothing to do with Prime reward markets. The card will render the wrong token icons and symbols paired with arbitrary cent values, actively misleading users. Even as temporary placeholder data, pairing hardcoded amounts with arbitrary tokens is likely to produce a confusing UI on any real environment. Consider substituting a static fallback (e.g. hardcoded token stubs or an empty array) until the real API hook is wired up.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are placeholder tokens until the API hook lands; added a TODO noting they're unrelated to the real Prime markets and will be replaced.

@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for ./apps/evm

Status Category Percentage Covered / Total
🔵 Lines 81.73% 48251 / 59037
🔵 Statements 81.73% 48251 / 59037
🔵 Functions 62.92% 672 / 1068
🔵 Branches 73.13% 5523 / 7552
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
apps/evm/src/components/Icon/icons/dotShortcut.tsx 100% 50% 100% 100%
apps/evm/src/components/Icon/icons/index.ts 99.01% 0% 100% 99.01% 1
apps/evm/src/containers/MarketFormModal/index.tsx 86.11% 60% 100% 86.11% 37-41
apps/evm/src/containers/MarketTable/index.tsx 94.18% 75% 66.66% 94.18% 97-105, 199
apps/evm/src/pages/PrimeLeaderboard/index.tsx 100% 60% 100% 100%
apps/evm/src/pages/PrimeLeaderboard/MarketActionsButton/index.tsx 100% 50% 50% 100%
apps/evm/src/pages/PrimeLeaderboard/MarketRewardRow/index.tsx 100% 0% 100% 100%
apps/evm/src/pages/PrimeLeaderboard/TotalRewardsCard/index.tsx 100% 0% 100% 100%
apps/evm/src/pages/PrimeLeaderboard/TotalRewardsSection/index.tsx 100% 0% 100% 100%
apps/evm/src/pages/PrimeLeaderboard/UserRewardsCard/index.tsx 100% 91.66% 100% 100%
apps/evm/src/pages/PrimeLeaderboard/UserRewardsSection/index.tsx 52.5% 0% 100% 52.5% 25-48
apps/evm/src/pages/PrimeLeaderboard/useGetPrimeTotalRewards/index.ts 92.3% 50% 100% 92.3% 1
apps/evm/src/pages/PrimeLeaderboard/useGetPrimeUserRewards/index.ts 94.44% 50% 100% 94.44% 1
Generated in workflow #13694 for commit 6085a57 by the Vitest Coverage Report Action

@cuzz-venus

Copy link
Copy Markdown
Contributor Author

@greptile review again

@cuzz-venus

Copy link
Copy Markdown
Contributor Author

@greptile review again

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about moving this component to the containers directory and reusing it in the MarketTable component (https://github.com/VenusProtocol/venus-protocol-interface/blob/088de2b0451f8a4ef5364cbaa7e3d2133b4d9bc8/apps/evm/src/containers/MarketTable/index.tsx) which renders the same UI using the renderRowControl property?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MarketTable and the Prime button use it now. I kept the buttons separate rather than reusing the Prime button as MarketTable's renderRowControl, because MarketTable's row click goes through a gated-asset acknowledgement flow (GatedAssetAcknowledgementModal) before opening the form — reusing the self-contained Prime button would bypass that.
Or do we need move the gated logic into the shared component?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting. I think we need to move the gating logic too, because it would also apply in the case of the Prime leaderboard.

So I'd say that MarketFormModal should also be in charge of checking if the user has accepted the conditions for using gated assets and display the acknowledgement modal (GatedAssetAcknowledgementModal) instead of the form modal if not.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sense. let me handle this logic

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved the gating into MarketFormModal itself, so it now checks isGated against the user's acknowledgement and shows GatedAssetAcknowledgementModal instead of the form when needed. MarketTable no longer handles it, and the Prime leaderboard's MarketActionsButton now gets the gating

Comment thread apps/evm/src/pages/PrimeLeaderboard/MarketActions/index.tsx Outdated
@cuzz-venus

Copy link
Copy Markdown
Contributor Author

@greptile review again

@therealemjy

therealemjy commented Jun 22, 2026

Copy link
Copy Markdown
Member

PR looks good to me, only one comment left to address (about the gating logic for the market form modal) otherwise it's ready to be merged.

Base automatically changed from feat/prime-leaderboard-table to main June 22, 2026 13:23
@cuzz-venus

Copy link
Copy Markdown
Contributor Author

PR looks good to me, only one comment left to address (about the gating logic for the market form modal) otherwise it's ready to be merged.

@therealemjy thanks!

addressed with - moved the gating into MarketFormModal itself, so it now checks isGated against the user's acknowledgement and shows GatedAssetAcknowledgementModal instead of the form when needed. MarketTable no longer handles it, and the Prime leaderboard's MarketActionsButton now gets the gating

cuzz-venus and others added 6 commits June 23, 2026 01:39
Drive the user rewards card headline by Prime eligibility (rewards amount,
eligible-to-supply prompt, or not-eligible prompt) and render per-market
Prime APYs with the shared Apy component.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@therealemjy

Copy link
Copy Markdown
Member

@cuzz-venus Very nice, approved.

@cuzz-venus cuzz-venus merged commit 8400929 into main Jun 23, 2026
5 checks passed
@cuzz-venus cuzz-venus deleted the feat/prime-total-rewards branch June 23, 2026 08:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants